package com.demo.encodeDecode.base64;

import lombok.extern.slf4j.Slf4j;

/**
 *
 * Base64编码原理与应用
 * http://blog.xiayf.cn/2016/01/24/base64-encoding/
 *
 * Created by liangqingqing on 2018/5/11.
 */
@Slf4j
public class Base64Util {

    /**
     * 编码，只是了解编码的原理，效率很低
     * @param str
     * @return
     */
    public static String encode(String str){
        byte[] binaryData = str.getBytes();
        //余数
        int yushu = binaryData.length%3;

        String hexStr = conver2HexStr(binaryData);
        log.info("二进制字符串:{}",hexStr);
        String newHexStr = getGroup4String(hexStr);
        log.info("改变编组二进制字符串:{}",newHexStr);
        StringBuilder sb = new StringBuilder();
        String byteStr = null;
        Byte newByte= null;
        for(int i =0;i<newHexStr.length();i=i+8){
            byteStr  = newHexStr.substring(i,i+8);
            newByte = Byte.valueOf( byteStr,2);
            sb.append(getChar(newByte));
        }

        //最后补充 "="
        if(yushu == 1){
            sb.append("==");
        }
        if(yushu == 2){
            sb.append("=");
        }

        return sb.toString();
    }


    /**
     * byte数组转换为二进制字符串
     * **/
    public static String conver2HexStr(byte [] b)
    {
        StringBuilder result = new StringBuilder();
        for(int i = 0;i<b.length;i++)
        {
            result.append(Integer.toBinaryString((b[i] & 0xFF) + 0x100).substring(1));
        }
        return result.toString();
    }

    /**
     * 二进制字符串转为4个一组的字符串
     * @param str2Hex 原始的二进制字符串
     * @return
     */
    private  static  String getGroup4String(String str2Hex){
        StringBuilder sb = new StringBuilder();
        int j = 0;

        for(int i = 0;i<str2Hex.length();i= i+6){
            j = i + 6 ;
            if(j <= str2Hex.length()){
                sb.append("00").append(str2Hex.substring(i,i+6));
            }else{
                //最后多余出来的前面补0
                int seroCount = 8 -(str2Hex.length() -i) ;

                for(int s=0;s<seroCount ;s++){
                    sb.append("0");
                }
                sb.append(str2Hex.substring(i,str2Hex.length()));
            }

        }
        return sb.toString();
    }





    /**
     * 八位字节对应的字符，前两位是'00'
     * @param byte8
     */
    private static  char getChar(byte byte8){
        //字节数组转换为十进制数字
        int i = Byte.toUnsignedInt(byte8);

        char[] chars = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
            'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
        };

        return chars[i];

    }




    /**
     * 解码，待实现
     * @param base64Str base64编码的字符串
     * @return 返回原始字符串
     */
    public static String decode(String base64Str){
        return null;
    }
}
